﻿#include "ZMultiThreadCtrl.h"
#include <QThreadPool>
#include <QDebug>

ZFLIB_BEGIN_NAMESPACE

ZMultiThreadCtrl::ZMultiThreadCtrl(QObject *parent)
    : QObject(parent),
      m_mutex(QMutex::Recursive),
      m_max_thread_count(1)
{
    qDebug() << tr("Current idle thread count in this computer:")
             << QThread::idealThreadCount();

    // 默认只有一个线程，用户可以修改
    m_thread_pool.setMaxThreadCount(1);
}

ZMultiThreadCtrl::~ZMultiThreadCtrl()
{
    stopAll();
}

void ZMultiThreadCtrl::addTask(QSharedPointer<ZMultiThreadTask> task)
{
    if (!task) return;

    // 添加任务到任务队列
    QMutexLocker locker(&m_mutex);
    m_wait_task_queue.push_back(task);

    // 尝试启动新任务
    tryStartNewTask();
}

void ZMultiThreadCtrl::stopAll()
{
    QMutexLocker locker(&m_mutex);

    // 清除队列中的任务
    m_wait_task_queue.clear();

    // 停止所有执行任务
    QMapIterator<ZMultiThreadTask *, QSharedPointer<ZMultiThreadTask> > it(m_running_tasks);
    while (it.hasNext())
    {
        it.next();
        it.value()->stopCurrent();
    }

    // 等待线程退出
    m_thread_pool.clear();
    m_thread_pool.waitForDone(5000);

    // 清除正在执行的任务
    m_running_tasks.clear();
}

void ZMultiThreadCtrl::setMaxThreadCount(int max_thread_count)
{
    m_max_thread_count = qMax<int>(1, max_thread_count);
    m_max_thread_count = qMin<int>(QThread::idealThreadCount(), max_thread_count);
    m_thread_pool.setMaxThreadCount(m_max_thread_count);
}

void ZMultiThreadCtrl::tryStartNewTask()
{
    QMutexLocker locker(&m_mutex);
    if (m_wait_task_queue.isEmpty()) return;

    // 检查是否超出最大线程数，是则暂不执行，否则执行任务
    if (m_running_tasks.size() < m_max_thread_count)
    {
        // 取出队列中等待最久的任务
        QSharedPointer<ZMultiThreadTask> task = m_wait_task_queue.takeFirst();

        // 监听结束信号
        disconnect(task.data(), SIGNAL(sigProgressFinished()), this, NULL);
        connect(task.data(), SIGNAL(sigProgressFinished()),
                this, SLOT(slotTaskProgressFinished()));

        // 仍然有可能失败，因为可能其他地方也在使用线程
        bool start_ok = m_thread_pool.tryStart(task.data());
        if (!start_ok) // 没启动成功，则放回队列继续等待
        {
            m_wait_task_queue.prepend(task);
            qDebug() << "Task start failed!";

            // 取消信号连接
            disconnect(task.data(), SIGNAL(sigProgressFinished()), this, NULL);
        }
        else
        {
            m_running_tasks[task.data()] = task;
            qDebug() << "Task start succeed!";
        }
    }
}

void ZMultiThreadCtrl::slotTaskProgressFinished()
{
    ZMultiThreadTask *task = qobject_cast<ZMultiThreadTask *>(sender());
    if (task)
    {
        // 将任务从当前正在执行的任务队列中移除
        QMutexLocker locker(&m_mutex);
        m_running_tasks.remove(task);
    }

    // 开始新的任务
    tryStartNewTask();
}

ZFLIB_END_NAMESPACE
